package com.sky.migrate.config;

import com.sky.migrate.common.CustomSqlSessionTemplate;
import com.sky.migrate.common.DataSourceConfigUtil;
import com.sky.migrate.common.DataSourceType;
import com.sky.migrate.common.DynamicDataSource;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@MapperScan(basePackages = "com.sky.biz" ,sqlSessionTemplateRef = "sqlSessionTemplate")
public class DatasourceConfig {

    @Value("${db-migrate.key}")
    private String key;

    @Primary
    @Bean("mysqlDataSource")
    public DataSource mysqlDataSource(Environment environment) {
        HikariConfig hikariConfig = DataSourceConfigUtil.setDataSourceEnvConfig("spring.datasource.mysql.", environment);
        HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
        return hikariDataSource;
    }

    @Bean("oracleDataSource")
    public DataSource oracleDataSource(Environment environment) {
        HikariConfig hikariConfig = DataSourceConfigUtil.setDataSourceEnvConfig("spring.datasource.oracle.", environment);
        HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
        return hikariDataSource;
    }


    @Bean("mysqlSqlSessionFactory")
    public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource,
                                                    @Qualifier("prepareInterceptor") PrepareInterceptor prepareInterceptor) throws Exception {
        return createSqlSessionFactory(dataSource, prepareInterceptor);
    }

    @Bean("oracleSqlSessionFactory")
    public SqlSessionFactory oracleSqlSessionFactory(@Qualifier("oracleDataSource") DataSource dataSource,
                                                     @Qualifier("prepareInterceptor") PrepareInterceptor prepareInterceptor) throws Exception {
        return createSqlSessionFactory(dataSource, prepareInterceptor);
    }

    @Bean("sqlSessionTemplate")
    public CustomSqlSessionTemplate sqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory mysqlSqlSessionFactory,
                                                       @Qualifier("oracleSqlSessionFactory") SqlSessionFactory oracleSqlSessionFactory) {
        Map<DataSourceType.Type, SqlSessionFactory> targetSqlSessionFactory = new HashMap<>(2);
        targetSqlSessionFactory.put(DataSourceType.Type.MYSQL, mysqlSqlSessionFactory);
        targetSqlSessionFactory.put(DataSourceType.Type.ORACLE, oracleSqlSessionFactory);

        CustomSqlSessionTemplate customSqlSessionTemplate = new CustomSqlSessionTemplate(mysqlSqlSessionFactory);
        customSqlSessionTemplate.setTargetSqlSessionFactory(targetSqlSessionFactory);
        customSqlSessionTemplate.setDefaultTargetSqlSessionFactory(mysqlSqlSessionFactory);
        return customSqlSessionTemplate;
    }

    @Bean("dynamicDataSource")
    public DynamicDataSource dynamicDataSource(@Qualifier("mysqlDataSource") DataSource mysqlDataSource,
                                               @Qualifier("oracleDataSource") DataSource oracleDataSource
    ) {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSource = new HashMap<>();
        targetDataSource.put(DataSourceType.Type.MYSQL, mysqlDataSource);
        targetDataSource.put(DataSourceType.Type.ORACLE, oracleDataSource);
        dynamicDataSource.setTargetDataSources(targetDataSource);
        dynamicDataSource.setDefaultTargetDataSource(mysqlDataSource);
        return dynamicDataSource;
    }

    private SqlSessionFactory createSqlSessionFactory(DataSource dataSource, PrepareInterceptor prepareInterceptor) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        // 添加mybatis插件拦截器，每次执行sql都能执行interceptor
        sqlSessionFactoryBean.setPlugins(prepareInterceptor);

        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setUseGeneratedKeys(false);
        configuration.setJdbcTypeForNull(JdbcType.OTHER);
        // 设置databaseId
        configuration.setDatabaseId(key);

        sqlSessionFactoryBean.setConfiguration(configuration);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper/*.xml"));
        return sqlSessionFactoryBean.getObject();
    }

}
